package com.xiashitech.agent.instrumentation.dubbo.inst;

import com.google.auto.service.AutoService;
import io.opentelemetry.javaagent.extension.instrumentation.HelperResourceBuilder;
import io.opentelemetry.javaagent.extension.instrumentation.InstrumentationModule;
import io.opentelemetry.javaagent.extension.instrumentation.TypeInstrumentation;
import io.opentelemetry.javaagent.extension.instrumentation.TypeTransformer;
import net.bytebuddy.description.type.TypeDescription;
import net.bytebuddy.matcher.ElementMatcher;

import java.util.Arrays;
import java.util.List;

import static io.opentelemetry.javaagent.extension.matcher.AgentElementMatchers.hasClassesNamed;
import static java.util.Collections.singletonList;
import static net.bytebuddy.matcher.ElementMatchers.named;

@AutoService(InstrumentationModule.class)
public class DubboInstrumentationModule extends InstrumentationModule {
    public DubboInstrumentationModule() {
        super("xs-apache-dubbo","xs-apache-dubbo-lt2.7");
    }

    @Override
    public void registerHelperResources(HelperResourceBuilder helperResourceBuilder) {
        helperResourceBuilder.registerForAllClassLoaders(
                "META-INF/services/com.alibaba.dubbo.rpc.Filter",
                "xs-classloader-resources/com.alibaba.dubbo.rpc.Filter");
    }

    @Override
    public List<String> getAdditionalHelperClassNames() {
        return Arrays.asList("com.xiashitech.agent.instrumentation.dubbo.inst.XSDubboFilter",
                "com.xiashitech.agent.instrumentation.dubbo.common.inst.internal.DubboNetClientAttributesGetter",
                "com.xiashitech.agent.instrumentation.dubbo.common.inst.internal.DubboNetServerAttributesGetter",
                "com.xiashitech.agent.instrumentation.dubbo.common.inst.DubboHeadersGetter",
                "com.xiashitech.agent.instrumentation.dubbo.common.inst.DubboHeadersSetter",
                "com.xiashitech.agent.instrumentation.dubbo.common.inst.DubboRequest",
                "com.xiashitech.agent.instrumentation.dubbo.common.inst.DubboRpcAttributesGetter",
                "com.xiashitech.agent.instrumentation.dubbo.common.inst.DubboTelemetry",
                "com.xiashitech.agent.instrumentation.dubbo.common.inst.DubboTelemetryBuilder",
                "com.xiashitech.agent.instrumentation.dubbo.common.inst.TracingFilter",
                "com.xiashitech.agent.instrumentation.dubbo.inst.XSDubboAttributesExtractor",
                "com.xiashitech.agent.instrumentation.dubbo.common.inst.reentry.DubboReentryHeadersGetter",
                "com.xiashitech.agent.instrumentation.dubbo.common.inst.reentry.DubboReentryHeadersSetter");
    }

    @Override
    public ElementMatcher.Junction<ClassLoader> classLoaderMatcher() {
        return hasClassesNamed("com.alibaba.dubbo.rpc.Filter");
    }

    @Override
    public List<TypeInstrumentation> typeInstrumentations() {
        return singletonList(new ResourceInjectingTypeInstrumentation());
    }

    public static class ResourceInjectingTypeInstrumentation implements TypeInstrumentation {
        @Override
        public ElementMatcher<TypeDescription> typeMatcher() {
            return named("com.alibaba.dubbo.common.extension.ExtensionLoader");
        }

        @Override
        public void transform(TypeTransformer transformer) {
        }
    }
}
